package com.insist.controller;

import com.insist.entity.UserInfo;
import com.insist.entity.ValidCode;
import com.insist.framework.CmmBaseResponse;
import com.insist.model.BannerModel;
import com.insist.service.ChargeService;
import com.insist.service.UserService;
import com.insist.service.ValidCodeService;
import com.insist.util.CmmUtils;
import com.insist.util.FasterJsonTools;
import com.insist.util.aliyun.OSSObjectUtilOriginal;
import net.sf.json.JSONObject;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * Created by Administrator on 2016/6/29.
 */
@Controller
public class SystemController {

    Logger logger = LoggerFactory.getLogger(SystemController.class);

    @Autowired
    ValidCodeService validCodeService;

    @Autowired
    UserService userService;

    @Autowired
    ChargeService chargeService;

    @RequestMapping(value = "/sendRegisterSms")
    @ResponseBody
    public CmmBaseResponse sendRegisterSms(HttpServletRequest request, Model model,String mobile) {
        //
        UserInfo user = userService.getByMobile(mobile);
        if(user!=null){
            return CmmBaseResponse.buildResponse(false,"该手机号已存在，请直接登录");
        }
        try {
            String validCode = CmmUtils.getValidCode(6);
            ValidCode code = validCodeService.save(mobile, validCode);
            HttpPost post = new HttpPost("https://sms.yunpian.com/v1/sms/send.json");
            List<NameValuePair> params = new ArrayList<NameValuePair>();
            params.add(new BasicNameValuePair("apikey", "66a885070f117fe1d387ac5bbd549da0"));
            params.add(new BasicNameValuePair("mobile", mobile));
            params.add(new BasicNameValuePair("text", "【insist】您的注册短信验证码为" + validCode + ",30分钟内输入有效"));
            params.add(new BasicNameValuePair("uid", ""+code.getId()));
            post.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));
            HttpClient client = HttpClientBuilder.create().build();
            if(!CmmUtils.IS_DEV){
                HttpResponse response = client.execute(post);
                String rs = EntityUtils.toString(response.getEntity(), "UTF-8");
                System.out.println(rs);
                Map<String,Object> map = FasterJsonTools.readValue2Map(rs, String.class, Object.class);
                if(!Integer.valueOf(0).equals(map.get("code"))){
                    CmmBaseResponse result = CmmBaseResponse.buildResponse(false, "短信发送失败，请稍后再试。");
                    result.setData(rs);
                    return result;
                }
            }
        }catch (Exception e){
            e.printStackTrace();
            return CmmBaseResponse.buildResponse(false, "短信发送失败，请稍后再试。");
        }
        return CmmBaseResponse.buildResponse(true, "发送成功");
    }


    /**
     * 总参与活动人数
     * @return
     */
    @RequestMapping(value = "/getBannerInfo")
    @ResponseBody
    public BannerModel getBannerInfo() {
        BannerModel bannerModel = new BannerModel();
        bannerModel.setActivityNumber(userService.getTotalJoinNum());
        return bannerModel;
    }


    @RequestMapping(value = "/register")
    @ResponseBody
    public CmmBaseResponse register(HttpServletRequest request, Model model,String mobile,String validCode,String password) {
        try {
//            ValidCode code = validCodeService.findLastCode(mobile);
//            if(!code.getValidCode().equals(validCode)){
//                return CmmBaseResponse.buildResponse(false, "注册失败,验证码错误");
//            }
            CmmBaseResponse response= userService.register(mobile, password);
            if(response.getSuccess()){
                UsernamePasswordToken token = new UsernamePasswordToken(mobile, password);
                token.setRememberMe(true);
                Subject subject = SecurityUtils.getSubject();
                subject.login(token);
            }
            return response;
        }catch (Exception e){
            logger.error("注册失败",e);
            return CmmBaseResponse.buildResponse(false, "注册失败");
        }
    }


    @RequestMapping("/download/{key}")
    public ResponseEntity<byte[]> download(@PathVariable("key") String key) {
        byte[] buff = null;
        try {
            buff = OSSObjectUtilOriginal.getInstance().downloadFile(key);
        }catch (Exception e){
            logger.error("OSSObjectUtilOriginal.downloadFile key {} error {}",key,e);
        }
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
        headers.set("Content-Transfer-Encoding", "binary");
        headers.set("Content-Type", "image/jpeg");
        return new ResponseEntity(buff, headers, HttpStatus.OK);
    }

    @RequestMapping(value = "/getData")
    public void getData(HttpServletRequest request,HttpServletResponse response){
        String appId="";
        String uri="";
        response.setHeader("Location", "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" +
                appId +
                "&redirect_uri=" +
                uri
                + "&response_type=code&scope=snsapi_base&state=1#wechat_redirect");
        response.setStatus(302);
    }


    @RequestMapping("/webhook")
    @ResponseBody
    public String webhook(HttpServletRequest request) {
        try {
            StringBuffer json = new StringBuffer();
            String line = null;
            request.setCharacterEncoding("utf-8");
            BufferedReader reader = request.getReader();
            while ((line = reader.readLine()) != null) {
                json.append(line);
            }
            logger.info("recieve webhook message:"+json);
            JSONObject jsonObj = JSONObject.fromObject(json.toString());
            String sign = jsonObj.getString("sign");
            String timestamp = jsonObj.getString("timestamp");
            boolean status = verifySign(sign, timestamp);
            logger.info("recieve webhook result:"+status);
            if (status) { //验证成功 //请不要修改或删除
                // 此处需要验证购买的产品与订单金额是否匹配:
                // 验证购买的产品与订单金额是否匹配的目的在于防止黑客反编译了iOS或者Android app的代码，
                // 将本来比如100元的订单金额改成了1分钱，开发者应该识别这种情况，避免误以为用户已经足额支付。
                // Webhook传入的消息里面应该以某种形式包含此次购买的商品信息，比如title或者optional里面的某个参数说明此次购买的产品是一部iPhone手机，
                // 开发者需要在客户服务端去查询自己内部的数据库看看iPhone的金额是否与该Webhook的订单金额一致，仅有一致的情况下，才继续走正常的业务逻辑。
                // 如果发现不一致的情况，排除程序bug外，需要去查明原因，防止不法分子对你的app进行二次打包，对你的客户的利益构成潜在威胁。
                // 如果发现这样的情况，请及时与我们联系，我们会与客户一起与这些不法分子做斗争。而且即使有这样极端的情况发生，
                // 只要按照前述要求做了购买的产品与订单金额的匹配性验证，在你的后端服务器不被入侵的前提下，你就不会有任何经济损失。
                // 处理业务逻辑
                chargeService.updateUserInfo(jsonObj.getString("transaction_id"),jsonObj.getString("transaction_fee"),jsonObj.getString("channelType"));
                return "success";
            } else { //验证失败
                return "fail";
            }
        } catch (Exception e) {
            return "fail";
        }
    }

    boolean verify(String sign, String text, String key, String input_charset) {
        text = text + key;
        String mysign = DigestUtils.md5Hex(getContentBytes(text, input_charset));
        logger.info("mysign:" + mysign);
        long timeDifference = System.currentTimeMillis() - Long.valueOf(key);
        logger.info("timeDifference:" + timeDifference);
        if (mysign.equals(sign) && timeDifference <= 300000) {
            return true;
        } else {
            return false;
        }
    }
    boolean verifySign(String sign, String timestamp) {
        logger.info("sign:" + sign);
        logger.info("timestamp:" + timestamp);
        return verify(sign, CmmUtils.keyId + CmmUtils.keySecret,
                timestamp, "UTF-8");
    }
    byte[] getContentBytes(String content, String charset) {
        if (charset == null || "".equals(charset)) {
            return content.getBytes();
        }
        try {
            return content.getBytes(charset);
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException("MD5签名过程中出现错误,指定的编码集不对,您目前指定的编码集是:" + charset);
        }
    }


}
